﻿using System;
using System.Linq.Expressions;
using System.Diagnostics;

namespace Codemonk.Pease.Common
{
    /// <summary>
    /// 接口代理
    /// </summary>
    /// <typeparam name="T">要使用的数据格式</typeparam>
    public class InterfaceProxy<T>
    {
        /// <summary>
        /// 序列化器
        /// </summary>
        public ISerializater<T> Serializater { get; set; }
        /// <summary>
        /// 通讯器
        /// </summary>
        public ICommunicator<T> Communicator { get; set; }
        /// <summary>
        /// 接口服务器
        /// </summary>
        public InterfaceServer Server { get; set; }

        private T Serialize(object obj)
        {
            if (Serializater == null) throw new ArgumentNullException("序列化器为空");
            return Serializater.Serialize(obj);
        }

        private B DeSerialize<B>(T data)
        {
            if (Serializater == null) throw new ArgumentNullException("序列化器为空");
            return Serializater.Deserialize<B>(data);
        }

        private void Request<B>(T data, Action<Exception> error, Action<B> back)
        {
            if (Communicator == null) throw new ArgumentNullException("通讯器为空");
            if (Server == null) throw new ArgumentNullException("服务器为空");
            Communicator.Request(data, Server, e =>
            {
                if (error != null)
                    error(e);
            }, d =>
            {
                if (back != null)
                {
                    var ra = DeSerialize<ResponseAgreement<T>>(d);
                    if (ra == null)
                    {
                        if (error != null)
                            error(new Exception("服务器返回了错误的数据"));
                        return;
                    }
                    var em = ra.ErrorMessage;
                    if (!string.IsNullOrEmpty(em))
                    {
                        if (error != null)
                            error(new Exception(em));
                    }
                    else
                    {
                        var rdata = ra.Data;
                        var b = DeSerialize<B>(rdata);
                        back(b);
                    }
                }
            });
        }

        public void Invoke<I, E, B>(Expression<Func<I, Action<E, Action<Exception>, Action<B>>>> function, E entity, Action<Exception> error, Action<B> back)
        {
            if (back == null) return;
            var type = typeof(I);
            if (!type.IsInterface) throw new ArgumentException("类型I必须是接口");
            var interfaceName = type.AssemblyQualifiedName;
            if (function == null) throw new NullReferenceException("参数function为空");
            var ue = function.Body as UnaryExpression;
            var methodSignature = (ue.Operand as MethodCallExpression).Arguments[2].ToString();
            RequestAgreement<T> agreement = new RequestAgreement<T>
            {
                Data = Serialize(entity),
                InterfaceName = interfaceName,
                MethodSignature = methodSignature
            };
            var data = Serialize(agreement);
            Request(data, error, back);
        }
    }
}
